﻿using System;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Repositories;
using AdminFrame.Application.Contracts.Parameters;
using AdminFrame.Application.Contracts.Parameters.Dtos;
using AdminFrame.Domain.Parameters;

namespace AdminFrame.Application.Parameters
{
    public class ParameterAppService : AdminFrameAppService, IParameterAppService
    {
        private readonly IParameterRepository _parameterRepository;
        private readonly IParameterManager _parameterManager;

        public ParameterAppService(
            IParameterRepository parameterRepository,
            IParameterManager parameterManager)
        {
            _parameterRepository = parameterRepository;
            _parameterManager = parameterManager;
        }

        public async Task<ParameterDto> GetAsync(Guid id)
        {
            var parameter = await _parameterRepository.GetAsync(id);
            return ObjectMapper.Map<Parameter, ParameterDto>(parameter);
        }

        public async Task<PagedResultDto<ParameterDto>> GetListAsync(GetParameterListDto input)
        {
            var query = await _parameterRepository.GetQueryableAsync();

            query = query.WhereIf(!string.IsNullOrWhiteSpace(input.FilterText), x =>
                x.Name.Contains(input.FilterText!) ||
                x.Code.Contains(input.FilterText!) ||
                x.Description.Contains(input.FilterText!))
                .WhereIf(!string.IsNullOrWhiteSpace(input.Name), x => x.Name.ToLower().Contains(input.Name!.ToLower()))
                .WhereIf(!string.IsNullOrWhiteSpace(input.Code), x => x.Code.ToLower().Contains(input.Code!.ToLower()))
                .WhereIf(!string.IsNullOrWhiteSpace(input.Description), x => x.Description.ToLower().Contains(input.Description!.ToLower()))
                .WhereIf(input.Type.HasValue, x => x.Type == input.Type)
                .WhereIf(input.IsActive.HasValue, x => x.IsActive == input.IsActive);

            var totalCount = await AsyncExecuter.CountAsync(query);

            query = query.OrderBy(x => x.Code)
                        .Skip(input.SkipCount)
                        .Take(input.MaxResultCount);

            var parameters = await AsyncExecuter.ToListAsync(query);

            return new PagedResultDto<ParameterDto>(
                totalCount,
                ObjectMapper.Map<System.Collections.Generic.List<Parameter>, System.Collections.Generic.List<ParameterDto>>(parameters)
            );
        }

        public async Task<ParameterDto> CreateAsync(CreateUpdateParameterDto input)
        {
            var parameter = await _parameterManager.CreateAsync(
                input.Name,
                input.Code,
                input.Type,
                input.Description,
                input.IsActive
            );

            await _parameterRepository.InsertAsync(parameter);

            return ObjectMapper.Map<Parameter, ParameterDto>(parameter);
        }

        public async Task<ParameterDto> UpdateAsync(Guid id, CreateUpdateParameterDto input)
        {
            var parameter = await _parameterRepository.GetAsync(id);

            await _parameterManager.ChangeNameAsync(parameter, input.Name);
            await _parameterManager.ChangeCodeAsync(parameter, input.Code);
            await _parameterManager.ChangeActiveStatusAsync(parameter, input.IsActive);

            parameter.Type = input.Type;
            parameter.Description = input.Description;

            await _parameterRepository.UpdateAsync(parameter);

            return ObjectMapper.Map<Parameter, ParameterDto>(parameter);
        }

        public async Task DeleteAsync(Guid id)
        {
            await _parameterRepository.DeleteAsync(id);
        }
    }
}